package org.zsk.cs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.zsk.cs.dao.RoleDao;
import org.zsk.cs.domain.dto.UserDto;
import org.zsk.cs.domain.po.User;
import org.zsk.cs.dao.UserDao;
import org.zsk.cs.exception.BizException;
import org.zsk.cs.service.RoleService;
import org.zsk.cs.service.UserService;
import org.zsk.cs.util.common.AppConstants;
import org.zsk.fastdev.assign.Assign;
import org.zsk.fastdev.bean.BeanUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 用户 serviceImpl
 * </p>
 *
 * @author zsk
 * @version 1.0
 * Created on 2020/03/26
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserDao,User> implements UserService {

    private final UserDao userDao;
    private final RoleService roleService;
    private final RoleDao roleDao;
    private final PasswordEncoder passwordEncoder;
    private final Assign assign;
    private final RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    public UserServiceImpl(UserDao userDao, RoleService roleService, RoleDao roleDao, PasswordEncoder passwordEncoder, Assign assign, RedisTemplate<Object, Object> redisTemplate) {
        this.userDao = userDao;
        this.roleService = roleService;
        this.roleDao = roleDao;
        this.passwordEncoder = passwordEncoder;
        this.assign = assign;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean save(User entity) {
        //加密密码
        entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        super.save(entity);
        //为用户添加普通用户角色
        return roleService.addUserForRoleBatch(Collections.singletonList(entity.getId()), Collections.singletonList(4));
    }

    @Override
    public boolean saveBatch(Collection<User> entityList) {
        entityList.forEach(user -> {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        });
        return super.saveBatch(entityList);
    }

    @Override
    public boolean updateById(User entity) {
        //加密密码
        if (!StringUtils.isEmpty(entity.getPassword())){
            entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        }
        return super.updateById(entity);
    }

    @Override
    public Boolean userChangePassword(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userDao.updateById(user)==1;
    }

    @Override
    public boolean userResetPassword(User user, String emailVerifyCode){
        //验证码验证
        if (!emailVerifyCode.equals(redisTemplate.opsForValue()
                .get(AppConstants.EMAIL_VERIFY_CODE_PREFIX + user.getEmail()))){
            log.debug("正确验证码: "+redisTemplate.opsForValue()
                    .get(AppConstants.EMAIL_VERIFY_CODE_PREFIX + user.getEmail()));
            throw new BizException("邮箱验证码错误");
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userDao.update(user,new LambdaQueryWrapper<User>().eq(User::getEmail,user.getEmail()))==1;
    }

    @Override
    public Boolean userChangePersonalInfo(User user) {
        return userDao.updateById(user)==1;
    }

    @Override
    public Boolean disableUser(List<Integer> ids) {
        return this.update(new LambdaUpdateWrapper<User>()
                .set(User::getEnable,false)
                .in(User::getId,ids));
    }

    @Override
    public Page<User> searchUser(User user, Page<User> page) throws Exception {
        return userDao.selectPage(page, BeanUtils.bean2QueryWrapper(User.class,user));
    }

    @SneakyThrows
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user=userDao.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,username));
        if (user == null) {
            throw new UsernameNotFoundException("账户不存在!");
        }
        UserDto userDto=new UserDto();
        assign.assign(user,userDto);
        userDto.setRoles(roleDao.selectRolesByUserId(userDto.getId()));
        return userDto;
    }
}
